package com.bwda.dsrs.systemservice.controller;


import com.bwda.dsrs.base.centerbase.form.SortInfo;
import com.bwda.dsrs.base.centerbase.response.CentreCutPageResponse;
import com.bwda.dsrs.base.centerbase.response.CentreListResponse;
import com.bwda.dsrs.base.centerbase.response.ResponseEntity;
import com.bwda.dsrs.base.centerbase.util.OrderByUtil;
import com.bwda.dsrs.base.util.CopyUtil;
import com.bwda.dsrs.systemservice.annotations.NeedRole;
import com.bwda.dsrs.systemservice.aspect.LogTypeEnum;
import com.bwda.dsrs.systemservice.aspect.Loggable;
import com.bwda.dsrs.systemservice.domain.Constants;
import com.bwda.dsrs.systemservice.domain.condition.menu.MenuCondition;
import com.bwda.dsrs.systemservice.domain.exception.SystemServiceException;
import com.bwda.dsrs.systemservice.domain.form.menu.*;
import com.bwda.dsrs.systemservice.domain.po.menu.MenuPo;
import com.bwda.dsrs.systemservice.domain.vo.menu.MenuVo;
import com.bwda.dsrs.systemservice.service.MenuService;
import com.bwda.dsrs.systemservice.service.OrderByConstants;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单表
 *
 * @author yangjun
 */
@RestController
@RequestMapping("/s/menu")
@Api(value = "/s/menu", tags = "菜单表")
public class MenuController extends BaseController {

    @Autowired
    private MenuService menuService;

    @ApiOperation(value = "查询菜单表", notes = "查询菜单表", httpMethod = "GET")
    @Loggable(descp = "查询菜单表", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/query", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<MenuVo> query(@ApiParam(value = "菜单ID", required = true) @RequestParam Integer id) throws SystemServiceException {
        MenuPo po = menuService.queryWithValid(id);
        MenuVo vo = CopyUtil.transfer(po, MenuVo.class);
        return getSuccessResult(vo);
    }

    @ApiOperation(value = "查询菜单表数量", notes = "查询菜单表数量", httpMethod = "GET")
    @Loggable(descp = "查询菜单表数量", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryCount", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<Integer> queryCount(@ModelAttribute @Valid MenuQueryForm form) throws SystemServiceException {
        MenuCondition condition = this.getConditionByQueryForm(form);
        int count = menuService.queryCount(condition);
        return getSuccessResult(count);
    }

    @ApiOperation(value = "查询菜单表列表", notes = "查询菜单表列表", httpMethod = "GET")
    @Loggable(descp = "查询菜单表列表", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryList", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<CentreListResponse<MenuVo>> queryList(@ModelAttribute @Valid MenuQueryForm form) throws SystemServiceException {
        MenuCondition condition = this.getConditionByQueryForm(form);
        List<MenuPo> poList = menuService.queryList(condition);
        List<MenuVo> voList = CopyUtil.transfer(poList, MenuVo.class);
        return getSuccessResult(getListResponse(voList));
    }

    @ApiOperation(value = "查询菜单表列表TREE", notes = "查询菜单表列表TREE", httpMethod = "GET")
    @Loggable(descp = "查询菜单表列表TREE", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryMenuTreeList", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<CentreListResponse<MenuTree>> queryMenuTreeList(@ModelAttribute @Valid MenuQueryForm form) throws SystemServiceException {
        MenuCondition condition = this.getConditionByQueryForm(form);
        List<MenuTreeForm> poList = menuService.queryTreeList(condition);
        List<MenuTree> treeList = menuService.queryMenuTree(poList);
        return getSuccessResult(getListResponse(treeList));
    }

    @ApiOperation(value = "查询菜单表列表(带分页)", notes = "查询菜单表列表(带分页)", httpMethod = "GET")
    @Loggable(descp = "查询菜单表列表(带分页)", type = LogTypeEnum.QUERY, include = "")
    @RequestMapping(value = "/queryPageList", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<CentreCutPageResponse<MenuVo>> queryPageList(@ModelAttribute @Valid MenuQueryForm form) throws SystemServiceException {
        MenuCondition condition = this.getConditionByQueryForm(form);
        List<MenuVo> voList = new ArrayList<>();
        int count = menuService.queryCount(condition);
        if (count > 0) {
            List<MenuPo> poList = menuService.queryList(condition);
            voList = CopyUtil.transfer(poList, MenuVo.class);
        }
        return getSuccessResult(getPageResponse(form, count, voList));
    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "新增菜单表", notes = "新增菜单表", httpMethod = "POST")
    @Loggable(descp = "新增菜单表", type = LogTypeEnum.CREATE, include = "")
    @RequestMapping(value = "/add", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<MenuVo> add(@ModelAttribute @Valid MenuCreateForm form) throws SystemServiceException {
        ResponseEntity<MenuVo> responseEntity = new ResponseEntity<>();
        if (form.getMenuCode() != null && form.getMenuName() != null && form.getIsShow() != null) {
            MenuPo po = CopyUtil.transfer(form, MenuPo.class);
            po.setIsSysMenu(0);
            menuService.insert(po);
            MenuVo vo = CopyUtil.transfer(po, MenuVo.class);
            return getSuccessResult(vo);
        }
        return responseEntity;
    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "修改菜单表", notes = "修改菜单表", httpMethod = "POST")
    @Loggable(descp = "修改菜单表", type = LogTypeEnum.UPDATE, include = "")
    @RequestMapping(value = "/update", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity update(@ModelAttribute @Valid MenuUpdateForm form) throws SystemServiceException {
        MenuPo po = CopyUtil.transfer(form, MenuPo.class);
        //装载
        MenuCondition condition = new MenuCondition();
        condition.setMenuName(form.getMenuName());
        condition.setId(form.getId());
        int count = menuService.countByName(condition);
        //判断除自己以为是否存在相同的菜单名称
        if (count > 0) {
            return getFailResult("已存在相同的菜单名");
        }

        menuService.update(po);
        return getSuccessResult();
    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "删除菜单表", notes = "删除菜单表", httpMethod = "POST")
    @Loggable(descp = "删除菜单表", type = LogTypeEnum.DELETE, include = "")
    @RequestMapping(value = "/delete", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity delete(@ApiParam(value = "菜单ID", required = true) @RequestParam Integer id) throws SystemServiceException {
        menuService.delete(id);
        return getSuccessResult();
    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "菜单上移", notes = "菜单上移", httpMethod = "POST")
    @Loggable(descp = "菜单上移", type = LogTypeEnum.SETTING, include = "")
    @RequestMapping(value = "/moveUp", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity moveUp(@ApiParam(value = "菜单上移", required = true) @RequestParam Integer id) throws SystemServiceException {
        exchangeNearOrder(id, true);
        return getSuccessResult();
    }

    @NeedRole("sysadminrole")
    @ApiOperation(value = "菜单下移", notes = "菜单下移", httpMethod = "POST")
    @Loggable(descp = "菜单下移", type = LogTypeEnum.SETTING, include = "")
    @RequestMapping(value = "/moveDown", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity moveDown(@ApiParam(value = "菜单下移", required = true) @RequestParam Integer id) throws SystemServiceException {
        exchangeNearOrder(id, false);
        return getSuccessResult();
    }

    /**
     * MenuQueryForm转换为MenuCondition
     *
     * @param form
     * @return
     */
    private MenuCondition getConditionByQueryForm(MenuQueryForm form) {
        MenuCondition condition = CopyUtil.transfer(form, MenuCondition.class);
        return condition;
    }

    /**
     * 查询所有菜单树
     */
    private List<MenuPo> getMenuTreeList(List<MenuPo> menuList, Integer parentMenuId) {
        // 查找所有菜单
        List<MenuPo> childrenList = new ArrayList<>();
        menuList.stream()
                .filter(d -> Objects.equals(parentMenuId, d.getParentMenuId()))
                .collect(Collectors.toList())
                .forEach(d -> {
                    if (Constants.MENU_ROOT_ID.equals(d.getParentMenuId().toString())) {
                        d.setChild(getMenuTreeList(menuList, d.getId()));
                        childrenList.add(d);
                    }
                });
        return childrenList;
    }

//    /**
//     * 递归取出所有关系树
//     *
//     * @param list
//     * @param parentMenuId
//     * @return
//     */
//    private List<MenuPo> getMenuTree(List<MenuPo> list, Integer parentMenuId) {
//        List<MenuPo> menuList = new ArrayList<>();
//        //取出所有菜单
//        for (int i = 0; i < list.size(); i++) {
//            MenuPo menuPo = list.get(i);
//            //取出所有父菜单
//            if (Constants.MENU_ROOT_ID.equals(menuPo.getParentMenuId().toString())) {
//                if (menuPo.getParentMenuId() == 0) {
//                    menuPo.setChild(getMenuTree(list, menuPo.getParentMenuId()));
//                }
//                menuList.add(menuPo);
//            }
//
//        }
//        return menuList;
//    }

    /**
     * 取出所有关系树其它实现
     *
     * @param list
     * @param parentId
     * @return
     */
   /* private List<Map<String, Object>> getMenuTreeList(List<MenuPo> list, int parentId) {
        List<Map<String, Object>> menuList = new ArrayList<>();
        Map<String, Object> map;
        //取出所有菜单
        for (int i = 0; i < list.size(); i++) {
            MenuPo menuPo = list.get(i);
            //取出所有父菜单
            if (menuPo.getParentMenuId() == parentId) {
                //返回菜单加入父对象
                map = object2Map(menuPo);
                map.remove("createDate");
                list.remove(menuPo);
                if (Constants.MENU_ROOT_ID.equals(menuPo.getParentMenuId().toString())) {
                    map.put("child", getMenuTreeList(list, menuPo.getParentMenuId()));
                } else {
                    map.remove("child");
                }
                menuList.add(map);
            }

        }
        return menuList;
    }*/


    /**
     * 实体对象转成Map
     *
     * @param obj 实体对象
     * @return
     */
    public static Map<String, Object> object2Map(Object obj) {
        Map<String, Object> map = new HashMap<>(16);
        if (obj == null) {
            return map;
        }
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                map.put(field.getName(), field.get(obj));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 交换相邻order的排序
     *
     * @param id
     * @param up
     * @return
     */
    private void exchangeNearOrder(Integer id, Boolean up) throws SystemServiceException {
        //原来的逻辑，看不懂，重写，先按照规则查询出所有的菜单
      /*  MenuCondition condition = new MenuCondition();
        condition.setId(id);*/
        MenuPo menu = menuService.queryWithValid(id);

        MenuCondition condition2 = new MenuCondition();
        condition2.setParentMenuId(menu.getParentMenuId());
//        List<SortInfo> sortInfos = new ArrayList<>();
//        SortInfo sortInfo = new SortInfo();
//        sortInfo.setSort("ASC");
//        sortInfo.setField("orderNum");
//        sortInfos.add(sortInfo);
//        condition2.setOrderBy(OrderByUtil.getOrderBy(sortInfos, OrderByConstants.Menu.ORDER_BY_MAP));
        List<MenuPo> menuPoList = menuService.queryList(condition2);

        //查出来之后，交换顺序，暂不考虑数据出错的情况，比如两个顺序都是3
        int index = 0;
        for (int i = 0; i < menuPoList.size(); i++) {
            if (id!= null && id.equals(menuPoList.get(i).getId())) {
                index = i;
            }
        }
        if (up) {
            index = index - 1;
            if (index < 0) {
                throw new SystemServiceException("无法上移");
            }
        } else {
            index = index + 1;
            if (index >= menuPoList.size()) {
                throw new SystemServiceException("无法下移");
            }
        }

        int orderNum = menu.getOrderNum();
        MenuPo menuPoThat = menuPoList.get(index);
        menu.setOrderNum(menuPoThat.getOrderNum());
        menuPoThat.setOrderNum(orderNum);
        menuService.update(menu);
        menuService.update(menuPoThat);

    }


}